package com.gl.order.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gl.order.commom.ResultBean;
import com.gl.order.commom.util.JwtTokenUtils;
import com.gl.order.commom.util.ResponseUtils;
import com.gl.order.config.JwtConfig;
import com.gl.order.entity.TUser;
import com.gl.order.security.model.SecurityToken;
import com.gl.order.security.model.SecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @Author: liangSY
 * @Date: 2021/6/8
 * @ClassName: TokenLoginFilter
 * @Description: TokenLoginFilter描述
 */
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter{


    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
    }
    // 获取表单提交的用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            TUser user = new ObjectMapper().readValue(request.getInputStream(), TUser.class);
//            if(JwtTokenUtils.isLoginOfKey(user.getAccount())){
//                log.info("该用户已经登陆");
//                ResponseUtils.responseJson(response,ResultBean.failed("该用户已登录"));
//                return null;
//            }
            return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(user.getAccount(), user.getPassword(), new ArrayList<>()));
        } catch (IOException e) {
            log.error(e.getMessage(),e);
            throw new RuntimeException();
        }
    }

    // 认证成功调用的方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // 认证成功后获得认证成功的信息
        SecurityUser principal = (SecurityUser) authResult.getPrincipal();
        // 根据用户名生成token
        String accessToken = JwtTokenUtils.createToken(principal);
        String refreshToken = JwtTokenUtils.createRefreshToken(principal);
        SecurityToken securityToken = new SecurityToken(accessToken,JwtConfig.tokenPrefix, JwtConfig.expirationTime,refreshToken);
        // 将用户名称和用户权限存放到缓存Redis中去，jwt时没有状态的登陆，需要登出或者其他操作需对其进行一个限制
        JwtTokenUtils.saveAccessToken(securityToken,principal);
        // 返回token
        ResponseUtils.responseJson(response, ResultBean.success(securityToken));
    }

    // 认证失败调用的方法
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        failed.printStackTrace();
        if(failed instanceof BadCredentialsException){
            ResponseUtils.responseJson(response, ResultBean.failed("账号或密码错误！"));
        }
        ResponseUtils.responseJson(response, ResultBean.failed(failed.getMessage()));
    }
}
